#include "third_block_area.h"
#include "application/map/area/area_manager.h"
#include "application/map/lift/lift_manager.h"
#include <QJsonObject>
#include <QJsonDocument>
#include <QNetworkRequest>
#include <QEventLoop>

namespace application {
namespace third_area {

ThirdBlockArea::ThirdBlockArea(const QString& areaId, int floor,
                               std::shared_ptr<kernel::ILogger> logger,
                               QObject* parent)
    : QObject(parent)
    , m_areaId(areaId)
    , m_floor(floor)
    , m_logger(logger)
{
    m_httpMgr = new QNetworkAccessManager(this);
}

void ThirdBlockArea::configureLiftLockResource(int liftNum, std::weak_ptr<lift::LiftManager> liftManager)
{
    m_liftNum = liftNum;
    m_liftManager = liftManager;
}

void ThirdBlockArea::preOccupy(int agvId)
{
    if (agvId < 0) {
        return;
    }
    if (!m_thirdPartyId.isEmpty() && m_thirdPartyId != QString::number(agvId)) {
        return;
    }
    if (m_isOccupied) {
        if (m_preOccupyAgvId == agvId || m_currentOccupyAgvId == agvId) {
            return;
        }
        return;
    }

    m_preOccupyAgvId = agvId;
    m_isOccupied = true;

    if (m_logger) {
        m_logger->debug(QString("第三方区域预占用: 区域=%1, AGV=%2")
            .arg(m_areaId).arg(agvId));
    }
}

bool ThirdBlockArea::tryAgvAcquire(int agvId)
{
    if (agvId < 0) {
        return false;
    }

    if (!m_isOccupied) {
        preOccupy(agvId);
        return true;
    }

    if (!m_thirdPartyId.isEmpty()) {
        return false;  // 外部占用时无论ID是否相同都视为冲突
    }

    if (m_currentOccupyAgvId == agvId || m_preOccupyAgvId == agvId) {
        return true;
    }

    return false;
}

bool ThirdBlockArea::thirdPartyOccupy(const QString& vehicleId)
{
    if (!m_isOccupied) {
        m_thirdPartyId = vehicleId;
        m_isOccupied = true;

        if (m_logger) {
            m_logger->info(QString("第三方车辆占用区域: 区域=%1, 车辆=%2")
                .arg(m_areaId).arg(vehicleId));
        }
        return true;
    }

    if (!m_thirdPartyId.isEmpty()) {
        return m_thirdPartyId == vehicleId;
    }

    if (m_logger) {
        m_logger->warning(QString("第三方车辆占用失败: 区域=%1, 车辆=%2")
            .arg(m_areaId).arg(vehicleId));
    }
    return false;
}

bool ThirdBlockArea::isThirdPartyOccupied(int agvId)
{
    Q_UNUSED(agvId);
    return m_isOccupied && !m_thirdPartyId.isEmpty();
}

void ThirdBlockArea::cancelOccupy(int agvId)
{
    bool released = false;

    if (m_isOccupied) {
        if (m_preOccupyAgvId == agvId) {
            m_preOccupyAgvId = -1;
            released = true;
        }
        if (m_currentOccupyAgvId == agvId) {
            m_currentOccupyAgvId = -1;
            released = true;
        }
    }

    if (released && m_logger) {
        m_logger->debug(QString("AGV取消占用: 区域=%1, AGV=%2")
            .arg(m_areaId).arg(agvId));
    }

    if (released) {
        if (m_liftLockOwner == QString::number(agvId)) {
            releaseLiftLock(m_liftLockOwner);
        }
        m_isOccupied = (m_currentOccupyAgvId != -1) ||
                       (m_preOccupyAgvId != -1) ||
                       !m_thirdPartyId.isEmpty();
    }
}

void ThirdBlockArea::cancelOccupy(const QString& vehicleId)
{
    if (m_isOccupied) {
        if (m_thirdPartyId == vehicleId) {
            m_isOccupied = false;
            m_thirdPartyId = "";

            if (m_logger) {
                m_logger->info(QString("第三方车辆取消占用: 区域=%1, 车辆=%2")
                    .arg(m_areaId).arg(vehicleId));
            }
            if (m_liftLockOwner == vehicleId) {
                releaseLiftLock(vehicleId);
            }
        }
    }
}

void ThirdBlockArea::forceRelease()
{
    m_isOccupied = false;
    m_preOccupyAgvId = -1;
    m_currentOccupyAgvId = -1;
    m_thirdPartyId = "";

    if (!m_liftLockOwner.isEmpty()) {
        releaseLiftLock(m_liftLockOwner);
    }

    if (m_logger) {
        m_logger->warning(QString("强制释放区域: 区域=%1").arg(m_areaId));
    }
}

void ThirdBlockArea::linkAreaManager(area::AreaManager* areaManager)
{
    m_areaManager = areaManager;
    if (!m_areaManager || m_areaManagerLinked) {
        return;
    }

    connect(m_areaManager, &area::AreaManager::areaEntered,
            this, &ThirdBlockArea::slot_onAreaEntered,
            Qt::UniqueConnection);

    connect(m_areaManager, &area::AreaManager::areaExited,
            this, &ThirdBlockArea::slot_onAreaExited,
            Qt::UniqueConnection);
    m_areaManagerLinked = true;
}

void ThirdBlockArea::sendPostRequest()
{
    QString url = "http://192.168.30.85:8005/api/traffic/action";
    QNetworkRequest requestInfo;
    requestInfo.setUrl(QUrl(url));
    requestInfo.setRawHeader("Content-Type", "application/json");

    QJsonObject obj;
    obj.insert("res", "occupy");
    obj.insert("action", "hold");
    obj.insert("rid", "1");

    QJsonDocument jsDoc(obj);
    QByteArray qByteHttpData = jsDoc.toJson();

    QNetworkReply* reply = m_httpMgr->post(requestInfo, qByteHttpData);
    connect(m_httpMgr, &QNetworkAccessManager::finished,
            this, &ThirdBlockArea::requestFinished);
}

bool ThirdBlockArea::acquireLiftLock(const QString& ownerId)
{
    if (m_liftNum <= 0) {
        return true;
    }

    if (!ownerId.isEmpty() && m_liftLockOwner == ownerId) {
        return true;
    }

    auto liftManager = m_liftManager.lock();
    if (!liftManager) {
        if (m_logger) {
            m_logger->warning(QString("共享电梯锁未初始化: 区域=%1, 电梯=%2").arg(m_areaId).arg(m_liftNum));
        }
        return false;
    }

    auto lift = liftManager->getLift(m_liftNum);
    if (!lift) {
        if (m_logger) {
            m_logger->warning(QString("共享电梯 %1 不存在，区域 %2 绑定失败").arg(m_liftNum).arg(m_areaId));
        }
        return false;
    }

    if (lift->isLocked() && !m_liftLockOwner.isEmpty()) {
        if (m_liftLockOwner == ownerId) {
            return true;
        }
        return false;
    }

    if (lift->isLocked() && m_liftLockOwner.isEmpty()) {
        return false;
    }

    lift->lock();
    m_liftLockOwner = ownerId;

    if (m_logger) {
        m_logger->info(QString("共享电梯锁占用成功: 区域=%1, 电梯=%2, 持有者=%3")
            .arg(m_areaId)
            .arg(m_liftNum)
            .arg(ownerId));
    }
    return true;
}

void ThirdBlockArea::releaseLiftLock(const QString& ownerId)
{
    if (m_liftNum <= 0) {
        return;
    }
    if (!m_liftLockOwner.isEmpty() && !ownerId.isEmpty() && m_liftLockOwner != ownerId) {
        return;
    }

    auto liftManager = m_liftManager.lock();
    if (liftManager) {
        if (auto lift = liftManager->getLift(m_liftNum)) {
            if (lift->isLocked()) {
                lift->unlock();
            }
        }
    }

    if (!m_liftLockOwner.isEmpty() && m_logger) {
        m_logger->info(QString("共享电梯锁释放: 区域=%1, 电梯=%2, 持有者=%3")
            .arg(m_areaId)
            .arg(m_liftNum)
            .arg(m_liftLockOwner));
    }

    m_liftLockOwner.clear();
}

void ThirdBlockArea::forceReleaseLiftLock()
{
    if (m_liftLockOwner.isEmpty()) {
        return;
    }
    releaseLiftLock(m_liftLockOwner);
}

void ThirdBlockArea::requestFinished(QNetworkReply* reply)
{
    QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    QNetworkReply::NetworkError err = reply->error();

    if (err != QNetworkReply::NoError) {
        if (m_logger) {
            m_logger->error(QString("第三方系统请求失败: %1").arg(reply->errorString()));
        }
    } else {
        if (m_logger) {
            m_logger->debug(QString("第三方系统响应: %1")
                .arg(QString(reply->readAll())));
        }
    }
}

void ThirdBlockArea::slot_enterArea(int agvId)
{
    if (!m_isOccupied) {
        if (m_preOccupyAgvId != agvId) {
            // 警告：未预占用就进入
        }
        m_preOccupyAgvId = agvId;
        m_currentOccupyAgvId = agvId;
        m_isOccupied = true;
    }
}

void ThirdBlockArea::slot_exitArea(int agvId)
{
    if (m_currentOccupyAgvId == agvId) {
        m_currentOccupyAgvId = -1;
    }
    if (m_preOccupyAgvId == agvId) {
        m_preOccupyAgvId = -1;
    }
    if (m_liftLockOwner == QString::number(agvId)) {
        releaseLiftLock(m_liftLockOwner);
    }
    m_isOccupied = (m_currentOccupyAgvId != -1) ||
                   (m_preOccupyAgvId != -1) ||
                   !m_thirdPartyId.isEmpty();
}

void ThirdBlockArea::slot_onAreaEntered(const QString& areaId, int agvId)
{
    if (areaId != m_areaId) {
        return;
    }
    slot_enterArea(agvId);
}

void ThirdBlockArea::slot_onAreaExited(const QString& areaId, int agvId)
{
    if (areaId != m_areaId) {
        return;
    }
    slot_exitArea(agvId);
}

} // namespace third_area
} // namespace application
